#ifndef __UTILS_H_
#define __UTILS_H_

/**
 * Desc: 工具方法集合
 * Auth: 张宇飞
 * Date: 2014-06-19    
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "err.h"
#include "config.h"

#ifdef __cplusplus
extern "C" {
#endif

#define CSB_YES_VRET(_p_)			do{if ((_p_)) return;}while(0)
#define CSB_NO_VRET(_p_)			do{if (!(_p_)) return;}while(0)
#define CSB_YES_RET(_p_, _ret_)			do{if ((_p_)) return (_ret_);}while(0)
#define CSB_NO_RET(_p_, _ret_)			do{if (!(_p_)) return (_ret_);}while(0)
#define CSB_YES_ERR_VRET(_p_, _e_)		do{if ((_p_)) {csberrno = _e_; return;}}while(0)
#define CSB_NO_ERR_VRET(_p_, _e_)		do{if (!(_p_)) {csberrno = _e_; return;}}while(0)
#define CSB_YES_ERR_RET(_p_, _e_, _ret_)	do{if ((_p_)) {csberrno = _e_; return (_ret_);}}while(0)
#define CSB_NO_ERR_RET(_p_, _e_, _ret_)		do{if (!(_p_)) {csberrno = _e_; return (_ret_);}}while(0)

#define CSB_SAFE_FREE(_p_)			do{if ((_p_)){ free((_p_)); (_p_) = NULL;}}while(0)
#define CSB_SAFE_DELETE(_p_)			do{if ((_p_)){ delete((_p_)); (_p_) = NULL;}}while(0)
#define RAND_VAR(_v_)			((0 == (_v_)) ? 0 : (((rand() % 2) ? 1 : -1) * ((float)(rand() % (int)(_v_ + 1)))))
#define RAND_VAR_INT(_v_)		((0 == (_v_)) ? 0 : (((rand() % 2) ? 1 : -1) * (rand() % (int)(_v_ + 1))))

#define CSB_FLAG_TEST(_flag_, _mask_)	((_flag_ & _mask_) == (_mask_))
#define CSB_FLAG_ON(_flag_, _mask_)	(_flag_ | _mask_)
#define CSB_FLAG_OFF(_flag_, _mask_)	(_flag_ & (~_mask_))
#define CSB_FLAG_TO(_c_, _f_, _m_)	((_c_) ? CSB_FLAG_ON(_f_, _m_) : CSB_FLAG_OFF(_f_, _m_))

#define ERROR_IS_TRUE(_data_, _cmp_)	((_data_) < (_cmp_) && (_data_) > -(_cmp_))

#define ZERO_MALLOC(_name_, _t_) \
	_t_* _name_ = (_t_*)malloc(sizeof(_t_));\
	memset(_name_, 0, sizeof(_t_))
#define ZERO_MALLOC_ARR(_name_, _t_, _n_) \
	_t_** _name_ = (_t_**)malloc(sizeof(_t_) * _n_);\
	memset(_name_, 0, sizeof(_t_) * _n_)

/* 日志 */
#ifdef CSB_DEBUG
#define CSB_LOG(_msg_, ...) fprintf(stderr, _msg_, ##__VA_ARGS__)
#else
#define CSB_LOG(_msg_, ...) do{}while(0)
#endif

#define CS_BUF_ARR_NAME(_t_)	_##_t_##_buf
#define CS_BUF_LIST_NAME(_t_)	_##_t_##_buf_##_list
#define CS_BUF_SIZE_NAME(_t_)	_t_##_BUF_SIZE
#define CS_BUF_DECLAR(_s_, _t_) \
	static const size_t CS_BUF_SIZE_NAME(_t_) = _s_; \
	static _t_	CS_BUF_ARR_NAME(_t_)[_s_];\
	static list_t	CS_BUF_LIST_NAME(_t_);

#define CS_BUF_INIT(_t_) do {\
	size_t i = CS_BUF_SIZE_NAME(_t_);\
	CSB_LOG(#_t_" buf size:%zu\n", CS_BUF_SIZE_NAME(_t_));\
	list_init(&CS_BUF_LIST_NAME(_t_));\
	while(i > 0) {\
		--i;\
		list_insert(&CS_BUF_LIST_NAME(_t_), (void*)(&CS_BUF_ARR_NAME(_t_)[i]), 0, 0);\
	} } while(0)

#define CS_BUF_END(_t_, _force_) \
	if (CS_BUF_LIST_NAME(_t_).size != CS_BUF_SIZE_NAME(_t_) && !force) {\
		CSB_LOG(#_t_" not recycled buffer variables:%zu，end buf \
may make application terminated\n", CS_BUF_SIZE_NAME(_t_) - CS_BUF_LIST_NAME(_t_).size);\
		return;\
	}\
	list_clear(&CS_BUF_LIST_NAME(_t_), NULL)

#define CS_BUF_RENT(_t_, _ret_) \
	_t_* _ret_ =NULL;\
	list_del(&CS_BUF_LIST_NAME(_t_), 0, (void**)(&_ret_));\
	CSB_LOG(#_t_" buf size:%zu，rent:%zu, avaiable:%zu\n", \
		CS_BUF_SIZE_NAME(_t_),  CS_BUF_SIZE_NAME(_t_) - CS_BUF_LIST_NAME(_t_).size,\
		CS_BUF_LIST_NAME(_t_).size)

#define CS_BUF_RETURN(_t_, _ele_) \
	CSB_NO_ERR_VRET(_ele_, CSBERR_PARAM); \
	list_insert(&CS_BUF_LIST_NAME(_t_), (void*)_ele_, 0, 0);\
	CSB_LOG(#_t_" buf size:%zu, after return rent num:%zu, avaiable:%zu\n", \
		CS_BUF_SIZE_NAME(_t_),  CS_BUF_SIZE_NAME(_t_) - CS_BUF_LIST_NAME(_t_).size,\
		CS_BUF_LIST_NAME(_t_).size)

/* 通用的系统初始化 */
extern CSB_DLL bool 		csb_common_init(float w, float h);
extern CSB_DLL void 		csb_common_end(bool force);

#ifdef __cplusplus
} /* end extern C */
#endif

#endif /* end of include guard: __UTILS_H_ */
